package com.scs.application.modules.sys.controller;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.core.consts.ErrorCode;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.mvc.controller.CrudController;
import com.scs.application.core.utils.FileUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.sys.entity.File;
import com.scs.application.modules.sys.model.RestResult;
import com.scs.application.modules.sys.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ClientAbortException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 系统文件上传表 前端控制器
 * </p>
 */
@RestController
@RequestMapping("/sys/file")
@Slf4j
public class FileController extends CrudController<FileService, File>{

    @Value("${res.real-path}")
    private String resPath;


    /***
     * @Description：根据 删除文件
     */
    @GetMapping("/delFilesByRef")
    public RestResult delFilesByRef(String fileId) {
        if (StringUtils.isBlank(fileId)) return RestResult.error("附件删除失败,缺少参数【fileId】");

        File fileDel = service.getOne(Wrappers.<File>query().eq("id", fileId));
        if (fileDel != null) {
            service.removeById(fileDel.getId());
            FileUtils.deleteFile(resPath + fileDel.getFilePath().replaceFirst("/res/", ""));
        }
        return RestResult.ok("附件删除成功");
    }

    /***
     * @Description：根据 关联信息查询文件列表
     */
    @PostMapping("/getFilesByRef")
    public RestResult getFilesByRef(@RequestBody Map<String, String> reqData) {
        String fileRefTable = reqData.get("fileRefTable");
        String fileRefId = reqData.get("fileRefId");
        String fileInfoIdArrStr = reqData.get("fileInfoIdArr");
        String fileInfoField = reqData.get("fileInfoField");
        if (StringUtils.isBlank(fileRefTable)) return RestResult.error("附件查询失败,缺少参数【refTable】");
        if (StringUtils.isBlank(fileRefId)) return RestResult.error("附件查询失败,缺少参数【refId】");

        List<File> files = service.list(Wrappers.<File>query().eq("ref_table", fileRefTable).eq("ref_id", fileRefId).orderByDesc("gmt_create")
        );
        return RestResult.ok("附件查询成功", files);
    }

    /**
     * 下载文件 根据绝对路径
     * @param response
     */
    @RequestMapping("downloadById")
    @ResponseBody
    public String downloadById(HttpServletResponse response, String fileId) {
        File fileInfo = service.getById(fileId);
        if (fileInfo == null) {
            log.error("下载失败，文件表未找到,文件id {}",fileId);
            return "下载失败，文件表未找到";
        }
        OutputStream os = null;

        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("application/octet-stream");
        try {
            response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileInfo.getFileName(), "UTF-8"));
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        }
        byte[] buff = new byte[1024];
        BufferedInputStream bis = null;
        try {
            os = response.getOutputStream();
            String filePath = resPath + fileInfo.getFilePath().replace("/res/", "");
            java.io.File file = new java.io.File(filePath);
            if (!file.exists()) {
                log.error("下载失败，本地磁盘不存在,文件id {}",fileId);
                return "下载失败，本地磁盘不存在";

            }
            bis = new BufferedInputStream(new FileInputStream(file));
            int i = bis.read(buff);
            while (i != -1) {
                os.write(buff, 0, buff.length);
                os.flush();
                i = bis.read(buff);
            }
        } catch (ClientAbortException e1) { //中止连接不做处理
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return "下载成功";
    }

    /**
     * 多文件上传
     *
     * @Description：多文件上传 【需要统一存放】
     */
    @RequestMapping(value = "/uploadMore", method = RequestMethod.POST)
    public RestResult uploadMore(@RequestParam Map<String, String> reqData, @RequestParam("file") MultipartFile file, HttpServletRequest request) {
        RestResult result = RestResult.ok("文件上传成功");
        //文件保存路径
        String fileSavePath = reqData.get("fileSavePath"), fileAccessPath;
        String refTable = reqData.get("fileRefTable");
        String refId = reqData.get("fileRefId");
        if (StringUtils.isBlank(fileSavePath)) fileSavePath = "tmp";
        fileSavePath += "/";
        fileAccessPath = fileSavePath;
        fileSavePath = resPath + fileSavePath;

        BufferedOutputStream stream = null;
        String fileName = IdUtil.getSnowflakeNextIdStr() + "." + FileUtils.getFileExtension(file.getOriginalFilename());
        try {
            FileUtils.mkdirs(fileSavePath);
            if (StringUtils.isBlank(refTable)) throw new BusinessException("缺少参数【refTable】");
            if (StringUtils.isBlank(refId)) throw new BusinessException("缺少参数【refId】");

            byte[] bytes = file.getBytes();
            stream = new BufferedOutputStream(new FileOutputStream(
                    new java.io.File(fileSavePath + fileName)));//设置文件路径及名字
            stream.write(bytes);// 写入
            stream.close();

            File fileSave = new File();
            fileSave.setRefId(refId);
            fileSave.setRefTable(refTable);
//            fileSave.setFileName(fileName);
            fileSave.setFileName(file.getOriginalFilename());
            fileSave.setFilePath("/res/" + fileAccessPath + fileName);
            service.save(fileSave);
            result.setData(fileSave);
        } catch (Exception e) {
            result.setMsg("文件上传失败," + e.getMessage());
            result.setCode(ErrorCode.COMMON_ERROR);
        }
        return result;
    }
}
